package com.caoustc.okhttplib.utils

import java.util.*

object ListUtils {
    const val DEFAULT_JOIN_SEPARATOR = ","
    fun <V> getSize(sourceList: List<V>?): Int {
        return sourceList?.size ?: 0
    }

    @kotlin.jvm.JvmStatic
    fun <V> isEmpty(sourceList: List<V>?): Boolean {
        return sourceList == null || sourceList.size == 0
    }

    fun <V> isEquals(actual: ArrayList<V>?, expected: ArrayList<V>?): Boolean {
        if (actual == null) {
            return expected == null
        }
        if (expected == null) {
            return false
        }
        if (actual.size != expected.size) {
            return false
        }
        for (i in actual.indices) {
            if (!ObjectUtils.isEquals(actual[i], expected[i])) {
                return false
            }
        }
        return true
    }

    fun join(list: List<String?>, separator: Char): String {
        return join(list, String(charArrayOf(separator)))
    }

    @JvmOverloads
    fun join(list: List<String?>, separator: String? = DEFAULT_JOIN_SEPARATOR): String {
        var separator = separator
        if (isEmpty(list)) {
            return ""
        }
        if (separator == null) {
            separator = DEFAULT_JOIN_SEPARATOR
        }
        val joinStr = StringBuilder()
        for (i in list.indices) {
            joinStr.append(list[i])
            if (i != list.size - 1) {
                joinStr.append(separator)
            }
        }
        return joinStr.toString()
    }

    fun <V> addDistinctEntry(sourceList: MutableList<V>?, entry: V): Boolean {
        return if (sourceList != null && !sourceList.contains(entry)) sourceList.add(entry) else false
    }

    fun <V> addDistinctList(sourceList: MutableList<V>?, entryList: List<V>): Int {
        if (sourceList == null || isEmpty(entryList)) {
            return 0
        }
        val sourceCount = sourceList.size
        for (entry in entryList) {
            if (!sourceList.contains(entry)) {
                sourceList.add(entry)
            }
        }
        return sourceList.size - sourceCount
    }

    fun <V> distinctList(sourceList: MutableList<V>): Int {
        if (isEmpty(sourceList)) {
            return 0
        }
        val sourceCount = sourceList.size
        var sourceListSize = sourceList.size
        for (i in 0 until sourceListSize) {
            var j = i + 1
            while (j < sourceListSize) {
                if (sourceList[i] == sourceList[j]) {
                    sourceList.removeAt(j)
                    sourceListSize = sourceList.size
                    j--
                }
                j++
            }
        }
        return sourceCount - sourceList.size
    }

    fun <V> addListNotNullValue(sourceList: MutableList<V>?, value: V?): Boolean {
        return if (sourceList != null && value != null) sourceList.add(value) else false
    }

    inline fun <reified V> getLast(sourceList: MutableList<V>?, value: V): V? {
        return if (sourceList == null) null else ArrayUtils.getLast<V?>(
            sourceList.toTypedArray(),
            value,
            true
        )
    }

    inline fun <reified V> getNext(sourceList: List<V>?, value: V): V? {
        return if (sourceList == null) null else ArrayUtils.getNext<V?>(
            sourceList.toTypedArray(),
            value,
            true
        ) as V
    }

    fun <V> invertList(sourceList: List<V>): List<V> {
        if (isEmpty(sourceList)) {
            return sourceList
        }
        val invertList: MutableList<V> = ArrayList(sourceList.size)
        for (i in sourceList.indices.reversed()) {
            invertList.add(sourceList[i])
        }
        return invertList
    }
}